#ifndef __ALSAAUDIOUTILS__H__
#define __ALSAAUDIOUTILS__H__

#include <alsa/asoundlib.h>

// ---------------------------------------------------------------- AlsaAudioPcm

typedef struct AlsaAudioPcm AlsaAudioPcm;
struct AlsaAudioPcm {
    snd_pcm_t *pcm;
    char *device;
    snd_pcm_stream_t stream;
    int mode;
};

int openAlsaAudioPcm(AlsaAudioPcm *pcm, char *name, snd_pcm_stream_t stream, int mode);

void closeAlsaAudioPcm(AlsaAudioPcm *pcm);

// 所需的PCM格式
// 所需的PCM访问权限
// 所需的PCM通道
// 所需的采样速率(单位Hz)
// 0=不允许alsa-lib重采样流,1=允许重采样
// latency 要求 us 的总延迟

// snd_pcm_set_params(snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
int setAlsaAudioPcmParam(AlsaAudioPcm *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency);

// ---------------------------------------------------------------- Readi/Writei
snd_pcm_sframes_t alsaAudioPcmRead(AlsaAudioPcm *pcm, void *buffer, snd_pcm_uframes_t size);
snd_pcm_sframes_t alsaAudioPcmWrite(AlsaAudioPcm *pcm, const void *buffer, snd_pcm_uframes_t size);
// -- 
int alsaAudioPcmRecover(AlsaAudioPcm *pcm, int err, int silent);

// ---------------------------------------------------------------- AlsaAudioPcmSwParams
// PCM 软件配置容器
typedef struct AlsaAudioPcmSwParams AlsaAudioPcmSwParams;
struct AlsaAudioPcmSwParams {

};

// ---------------------------------------------------------------- AlsaAudioPcmHwParams
// PCM 硬件配置容器
typedef struct AlsaAudioPcmHwParams AlsaAudioPcmHwParams;
struct AlsaAudioPcmHwParams {
    int channels;               // 通道
    int rate;                   // 采样率
    snd_pcm_format_t format;    // 数据格式
    snd_pcm_access_t access;    // 访问模式
    // int 

    // -- stream
    int stream_rate; // 

    // -- buffer
    int buffer_time; // 

    // other 
    AlsaAudioPcm *pcm;
    snd_pcm_hw_params_t *params;
};

// 或者 setAlsaAudioPcmHwParamsMalloc
void setAlsaAudioPcmHwParamsAlloca(AlsaAudioPcmHwParams *params);
// 或者 setAlsaAudioPcmHwParamsAlloca
void setAlsaAudioPcmHwParamsMalloc(AlsaAudioPcmHwParams *params);

// 使用 AlsaAudioPcm 设备初始化 AlsaAudioPcmHwParams
int setAlsaAudioPcmHwParamsAny(AlsaAudioPcmHwParams *params, AlsaAudioPcm *pcm);

// 通过一系列 set 来设置硬件参数中的基本参数
void setAlsaAudioPcmHwParamsChannels(AlsaAudioPcmHwParams *params, int channels);
void setAlsaAudioPcmHwParamsFormat(AlsaAudioPcmHwParams *params, snd_pcm_format_t format);
void setAlsaAudioPcmHwParamsAccess(AlsaAudioPcmHwParams *params, snd_pcm_access_t access);
void setAlsaAudioPcmHwParamsRate(AlsaAudioPcmHwParams *params, int rate, int dir);
int setAlsaAudioPcmHwParamsRateNear(AlsaAudioPcmHwParams *params, unsigned int *val, int *dir);
int setAlsaAudioPcmHwParamsPeriodSizeNear(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t *val, int *dir);
int setAlsaAudioPcmHwParamsPeriodTime(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t val, int dir);

// get AlsaAudioPcmHwParams
int getAlsaAudioPcmHwParamsChannels(AlsaAudioPcmHwParams *params, unsigned int *channels);
int getAlsaAudioPcmHwParamsPeriodSize(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t *frames, int *dir);
int getAlsaAudioPcmHwParamsPeriodTime(AlsaAudioPcmHwParams *params, unsigned int *val, int *dir);

// apply
int  applyAlsaAudioPcmHwParams(AlsaAudioPcmHwParams *params, AlsaAudioPcm *pcm);
// 释放不再使用的 AlsaAudioPcmHwParams
void freeAlsaAudioPcmHwParams(AlsaAudioPcmHwParams *params);

// ---------------------------------------------------------------- 

#endif  //!__ALSAAUDIOUTILS__H__